home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / awe2-0_1.lha / awe2-0.1 / Src / HardwareContext-ns32k.cc < prev    next >
C/C++ Source or Header  |  1990-07-09  |  5KB  |  198 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2. // 
  3. // Copyright (C) 1988 University of Illinois, Urbana, Illinois
  4. // Copyright (C) 1989 University of Colorado, Boulder, Colorado
  5. // Copyright (C) 1990 University of Colorado, Boulder, Colorado
  6. //
  7. // written by Dirk Grunwald (grunwald@foobar.colorado.edu)
  8. //
  9. #include "HardwareContext.h"
  10. #include "HardwareContextP.h"
  11. #include "CpuMultiplexor.h"
  12. #include "Thread.h"
  13. #include "assert.h"
  14. #include <stream.h>
  15.  
  16. //
  17. //    Many machines have the same (or very similar) stack format.
  18. //    The 68K & 32K are examples of such machines.
  19. //
  20. //    The const *registers* defines the number of additional longwords
  21. //    needed on the stack past the last frame pointer. This value needs
  22. //    to jibe with the one in HardwareContext-<arch>.s.
  23. //
  24.  
  25. const long MagicStackMarker = 0x464f4f20;    // this says 'FOO '
  26.  
  27. static const int expectedBytesSavedInContext
  28.     = 5 * 4     // data registers
  29.     + 2 * 8;    // floating registers
  30. static int numberOfBytesSavedInContext = 0;
  31. static void computeBytesSaved();
  32.  
  33.  
  34. HardwareContext::HardwareContext (int check, unsigned size)
  35. {
  36.     checkStackLimits = check;
  37.  
  38.     stackBase = 0;
  39.     stackEnd = 0;
  40.     stackMax = 0;
  41.     stackSize = 0;
  42.     stackCheck = 0;
  43.     stackMallocAt = 0;
  44.  
  45.     if (size > 0) {
  46.     stackSize = size;
  47.     stackMallocAt = new void *[ stackSize ];
  48.     //
  49.     // stackBase should point to the first writeable cell of the
  50.     // new stack.
  51.     //
  52.     stackEnd = stackMallocAt;
  53.     stackBase = &stackMallocAt[stackSize-1];
  54.     }
  55.     else {
  56.     //
  57.     // Have the main process figure out how many registers
  58.     // (actually, Quads) are pushed when we save an entire context.
  59.     //
  60.     computeBytesSaved();
  61.     assert( numberOfBytesSavedInContext == expectedBytesSavedInContext );
  62.     }
  63. }
  64.  
  65. HardwareContext::reclaimStack()
  66. {
  67.     if ( stackMallocAt ) {
  68.     if ( check ) {
  69.         mprotect(stackMallocAt, pageSizeInBytes, PROT_READ | PROT_WRITE);
  70.     }
  71.     free(stackMallocAt);
  72.     stackMallocAt = 0;
  73.     }
  74. }
  75.  
  76. void
  77. HardwareContext::magicSwitchTo(HardwareContext *to)
  78. {
  79.     asm (" " : : :
  80.      "r1", "r2", "r3", "r4", "r5", "r6", "r7",
  81.      "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7");
  82.  
  83.     asm __volatile("sprd    fp,%0" : "=g" (fp)) ;
  84.     asm __volatile("sprd    sp,%0" : "=g" (sp)) ;
  85.  
  86.     //
  87.     // I think I have to do it in this order to fetch the proper value
  88.     // of 'to' -- however, even here, it's not certain to work.
  89.  
  90.     asm __volatile("lprd    sp,%0" : : "g" (to -> sp)) ;
  91.     asm __volatile("lprd    fp,%0" : : "g" (to -> fp)) ;
  92. }
  93.  
  94. void
  95. HardwareContext::stackOverflow()
  96. {
  97.     register unsigned depth = stackBase - getSp();
  98.     if (stackMax < depth) {
  99.     stackMax = depth;
  100.     }
  101.     if ( stackMax >= stackSize ) {
  102.     cerr << "\nStack overflow\n";
  103.     cerr << " getSp() = " << hex(long(getSp()));
  104.     cerr << " and stackBase = " << hex(long(stackBase)) << "\n";
  105.     cerr << *this << "\n";
  106.     cerr << "Current task is \n";
  107.     cerr << *(CurrentThread());
  108.     cerr << "\n";
  109.     cerr.flush();
  110.     }
  111.     assert( stackMax < stackSize );
  112.     assert( *stackCheck == MagicStackMarker );
  113. }
  114.  
  115.  
  116. void
  117. HardwareContext::buildReturnFrame(void *returnThis, voidFuncP returnAddress)
  118. {
  119.     //
  120.     //    To build a thread, we return to the first address of startOff,
  121.     //    which will use the current FP & SP to build a local context,
  122.     //    and then call the user main.
  123.     //
  124.     //    startOff needs to have a valid frame. The return address for this
  125.     //    frame is NULL, since we never exit procedure startOff.
  126.     //
  127.     
  128.     stackCheck = (long *) stackBase;
  129.     register HardwareContextQuad **stack;
  130.     stack = (HardwareContextQuad **) stackBase;
  131.  
  132.     *(stack--) = (HardwareContextQuad *) MagicStackMarker;
  133.     *(stack--) = 0;            // return address
  134.     register HardwareContextQuad **startOffFp = stack;
  135.     *(stack--) = 0;            // frame pointer
  136.     
  137.     //
  138.     //    Construct the stack frame that will be used in procedure startOff.
  139.     //    startOff needs to know the value for *this*, which is passed in
  140.     //    as the first parameter. It also gets the back-link FP for the
  141.     //    last frame (build above).
  142.     //
  143.     
  144.     *(stack--) = (HardwareContextQuad *) returnThis;
  145.     register HardwareContextQuad **nullFp = stack;
  146.     //
  147.     // FP for previous frame
  148.     //
  149.     *(stack--) = (HardwareContextQuad *) startOffFp;
  150.     
  151.     //
  152.     //    Now build the stack frame that is used to return to startOff
  153.     //
  154.     
  155.     *(stack--) = (HardwareContextQuad *) returnAddress;
  156.     
  157.     fp = (HardwareContextQuad) stack;
  158.     
  159.     *(stack) = (HardwareContextQuad *) nullFp;
  160.  
  161.     //
  162.     //    casting to char saves us two insn's
  163.     //
  164.     char *foo = (char *) stack;
  165.  
  166.     foo -= numberOfBytesSavedInContext;
  167.     
  168.     sp = (HardwareContextQuad) foo;
  169. }
  170.  
  171. static void computeBytesSaved()
  172. {
  173.     //
  174.     //    Cause all registers to be pushed
  175.     //
  176.     asm (" " : : :
  177.      "r1", "r2", "r3", "r4", "r5", "r6", "r7",
  178.      "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7");
  179.  
  180.     long tempSp;
  181.     long tempFp;
  182.     asm __volatile("sprd    fp,%0" : "=g" (tempFp)) ;
  183.     asm __volatile("sprd    sp,%0" : "=g" (tempSp)) ;
  184.     numberOfBytesSavedInContext = tempFp - tempSp;
  185. }
  186.  
  187. void
  188. HardwareContext::classPrintOn(ostream& s)
  189. {
  190.     s << "[HardwareContext] Stack spans " << hex(long(stackEnd));
  191.     s << " to " << hex(long(stackBase));
  192.     s << " used is  " << (stackMax) << " of " << stackSize << "\n";
  193.     s << "[HardwareContext] fp = " << hex(long(fp));
  194.     s << " sp = " << hex(long(sp));
  195.     long p = *( (long *) fp );
  196.     s << " @fp = " << hex(p) << "\n";
  197. }
  198.